{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "## dehaze\n",
    "import numpy as np\n",
    "import cv2,math\n",
    "\n",
    "def darkChannel(p, winSize):\n",
    "    minChannel = p.min(axis=2)\n",
    "    \n",
    "    shape = cv2.MORPH_RECT\n",
    "    kernel = cv2.getStructuringElement(shape, winSize)\n",
    "    min_image = cv2.erode(minChannel, kernel)\n",
    "    return min_image\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "def guideFilter(I, p, winSize, eps):\n",
    "    \"\"\"\n",
    "    导向图像(Guidance Image) I，滤波输出图像(Filtering Input Image) p，均值平滑窗口半径 r，正则化参数 e。\n",
    "    利用导向滤波进行图像平滑处理时，通常令p=I。\n",
    "    其中：guideFilter(）函数调用opencv自带的库函数blur() 进行均值平滑。\n",
    "    :param I:\n",
    "    :param p:\n",
    "    :param winSize:\n",
    "    :param eps:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    \n",
    "    sqaure_avg = cv2.blur(p * p, winSize)\n",
    "    avg = cv2.blur(p, winSize)\n",
    "    \n",
    "    ak = (sqaure_avg - avg ** 2)/(sqaure_avg - avg **2 + eps)\n",
    "    bk = (-1 * ak + 1) * avg\n",
    "    \n",
    "    a = cv2.blur(ak, winSize)\n",
    "    b = cv2.blur(bk, winSize)\n",
    "    \n",
    "    q = a * p + b\n",
    "    \n",
    "    return q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def largest_indices(ary, n):\n",
    "    \"\"\"Returns the n largest indices from a numpy array.\"\"\"\n",
    "    flat = ary.flatten()\n",
    "    indices = np.argpartition(flat, -n)[-n:]\n",
    "    indices = indices[np.argsort(-flat[indices])]\n",
    "    return np.unravel_index(indices, ary.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def CalculateA(p, winSize):\n",
    "    \n",
    "    dark_p = darkChannel(p, winSize)\n",
    "    \n",
    "    h, w = dark_p.shape\n",
    "    top_pixels = h * w // 1000\n",
    "    \n",
    "    indexs = largest_indices(dark_p, top_pixels)\n",
    "    \n",
    "    A = p[indexs].max(axis=0)\n",
    "    \n",
    "    return A\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def CalculateTx(p, winSize,w=0.95):\n",
    "    \n",
    "    A = CalculateA(p,winSize)\n",
    "    \n",
    "    dark_t = darkChannel(p / A,winSize)\n",
    "    \n",
    "    t = 1 - w * dark_t\n",
    "    \n",
    "    return t\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def MistRemove(p, winSize,t0):\n",
    "    \n",
    "    A = CalculateA(p,winSize)\n",
    "    \n",
    "    p=p/255\n",
    "    dark_p = darkChannel(p,winSize)\n",
    "    \n",
    "    b, g, r = cv2.split(p)\n",
    "    gf1 = guideFilter(b, dark_p, winSize, math.pow(0.1,2))\n",
    "    gf2 = guideFilter(g, dark_p, winSize, math.pow(0.1,2))\n",
    "    gf3 = guideFilter(r, dark_p, winSize, math.pow(0.1,2))\n",
    "    \n",
    "#     gf1 = FastguideFilter(b, tx, winSize, math.pow(0.1,2),s=0.5)\n",
    "#     gf2 = FastguideFilter(g, tx, winSize, math.pow(0.1,2),s=0.5)\n",
    "#     gf3 = FastguideFilter(r, tx, winSize, math.pow(0.1,2),s=0.5)\n",
    "\n",
    "    gf = cv2.merge([gf1, gf2, gf3])\n",
    "    \n",
    "    gf = gf*255\n",
    "    gf[gf>255] = 255\n",
    "    gf = np.round(gf)\n",
    "    gf = gf.astype(np.uint8)\n",
    "    \n",
    "    t = 1 - gf * 0.95 / A\n",
    "    \n",
    "    \n",
    "    \n",
    "    t = cv2.max(t, t0)\n",
    "    \n",
    "   \n",
    "    \n",
    "\n",
    "    rows, cols, channels = gf.shape\n",
    "    \n",
    "    a = np.average(A)\n",
    "    \n",
    "    p = p*255\n",
    "    p[p>255] = 255\n",
    "    p = np.round(p)\n",
    "    p = p.astype(np.uint8)\n",
    "    \n",
    "    o = (p -a)/t+a\n",
    "    o = np.round(o)\n",
    "    o = o.astype(\"uint8\")\n",
    "    \n",
    "    o[o>255]=255\n",
    "    \n",
    "    res = np.hstack((p,o))\n",
    "    \n",
    "    cv2.imshow('1',res)\n",
    "    cv2.waitKey(0)\n",
    "    \n",
    "    return o\n",
    "    \n",
    "    \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[10, 10, 10],\n",
       "        [10, 10, 10],\n",
       "        [10, 10, 10],\n",
       "        ...,\n",
       "        [24, 24, 24],\n",
       "        [24, 24, 24],\n",
       "        [24, 24, 24]],\n",
       "\n",
       "       [[31, 33, 35],\n",
       "        [39, 42, 43],\n",
       "        [26, 29, 31],\n",
       "        ...,\n",
       "        [27, 20, 18],\n",
       "        [31, 23, 21],\n",
       "        [31, 23, 21]],\n",
       "\n",
       "       [[26, 29, 31],\n",
       "        [32, 35, 36],\n",
       "        [18, 21, 22],\n",
       "        ...,\n",
       "        [25, 18, 16],\n",
       "        [29, 21, 20],\n",
       "        [31, 23, 21]],\n",
       "\n",
       "       ...,\n",
       "\n",
       "       [[12, 12, 12],\n",
       "        [ 9,  9,  9],\n",
       "        [12, 12, 12],\n",
       "        ...,\n",
       "        [13, 14,  9],\n",
       "        [14, 16, 10],\n",
       "        [16, 17, 11]],\n",
       "\n",
       "       [[14, 14, 14],\n",
       "        [14, 14, 14],\n",
       "        [18, 18, 18],\n",
       "        ...,\n",
       "        [13, 14, 10],\n",
       "        [14, 16, 11],\n",
       "        [14, 16, 11]],\n",
       "\n",
       "       [[13, 13, 13],\n",
       "        [13, 13, 13],\n",
       "        [17, 17, 17],\n",
       "        ...,\n",
       "        [13, 14, 11],\n",
       "        [13, 14, 11],\n",
       "        [13, 14, 11]]], dtype=uint8)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p = cv2.imread(\"mist3.png\")\n",
    "MistRemove(p,(16,16), 0.1)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
